package com.informa.text;

import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Set;

import static com.informa.java.util.CollectionUtils.*;


public class CamelCaseFormat extends Format {

	private static final long serialVersionUID = -5897120644068997648L;

	private Set<Character> WORD_BOUNDARY_CHARACTERS = asSet(' ', ',', '/');

	@Override
	public StringBuffer format(Object object, StringBuffer toAppendTo,
			FieldPosition pos) {
		if (object == null) {
			toAppendTo.append("null");
		} else {
			String text = object.toString();
			String camelCased = getCamelCased(text);
			toAppendTo.append(camelCased);
		}

		return toAppendTo;
	}

	private String getCamelCased(String text) {

		if (text.length() == 0) return "";
		
		StringBuffer textBuffer = new StringBuffer(text.toLowerCase());
		capitaliseCharacterAt(textBuffer, 0);

		for (int i = 1; i < textBuffer.length(); i++) {
			char character = textBuffer.charAt(i);
			if (isWordBoundaryCharacter(character)
					&& hasMoreCharactersAfter(textBuffer, i)) {
				int targetCharacterIndex = i + 1;
				capitaliseCharacterAt(textBuffer, targetCharacterIndex);
			}

		}

		String camelCased = textBuffer.toString();

		return camelCased;
	}

	private void capitaliseCharacterAt(StringBuffer textBuffer,
			int targetCharacterIndex) {
		char toCapitalise = textBuffer.charAt(targetCharacterIndex);
		char capitalised = Character.toUpperCase(toCapitalise);
		textBuffer.setCharAt(targetCharacterIndex, capitalised);
	}

	private boolean hasMoreCharactersAfter(StringBuffer textBuffer, int i) {
		return textBuffer.length() - 1 > i;
	}

	private boolean isWordBoundaryCharacter(char character) {
		return WORD_BOUNDARY_CHARACTERS.contains(character);
	}

	@Override
	public Object parseObject(String source, ParsePosition pos) {
		pos.setIndex(source.length());
		return source;
	}

}
